﻿using System;
using System.Collections.Generic;
using System.Device.Location;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using FastestWays.Model;
using FastestWays.Model.WazeObjects;
using FastestWays.ViewModel;
using Newtonsoft.Json;
using Windows.Devices.Geolocation;

namespace WazePocWP8.Server
{
    public class WazeEngine
    {
        private RootObject _routeWazeResponse;
        private Geocoordinate _startuplocation;

        public WazeEngine(Geocoordinate startuplocation)
        {
            _startuplocation = startuplocation;
        }

        public async Task<bool> GetRoute()
        {
            _routeWazeResponse = await GetRouteFor(_startuplocation.Longitude, _startuplocation.Latitude, Parameters.Coordinate.Longitude, Parameters.Coordinate.Latitude, Parameters.CurrentCountry);
            return true;
        }

        public RootObject RouteWazeResponse
        {
            get { return _routeWazeResponse; }
        }

        private Task<RootObject> GetRouteFor(double fromX, double fromY, double toX, double toY, string country)
        {
            WebRequest httpRequest =  null;
            if (country == "ISR")
                httpRequest = WebRequest.Create(String.Format("http://www.waze.co.il/RoutingManager/routingRequest?from=x%3A{0}+y%3A{1}&to=x%3A{2}+y%3A{3}&returnJSON=false&returnGeometries=false&returnInstructions=true&timeout=60000&nPaths=1#", 
                                                              fromX, fromY, toX, toY));
            if (country == "USA")
                httpRequest = WebRequest.Create(String.Format("http://www.waze.com/RoutingManager/routingRequest?from=x%3A{0}+y%3A{1}&to=x%3A{2}+y%3A{3}&returnJSON=false&returnGeometries=false&returnInstructions=true&timeout=60000&nPaths=1#",
                                                              fromX, fromY, toX, toY));

            TaskCompletionSource<RootObject> tcs = new TaskCompletionSource<RootObject>();

            if (httpRequest != null)
                httpRequest.BeginGetResponse(state =>
                    {
                        var response = httpRequest.EndGetResponse(state);
                        using (var s = response.GetResponseStream())
                        using (var sr = new StreamReader(s))
                        {
                            string responseText = sr.ReadToEnd().Replace("NaN", "0.0");
                            var myResponse = JsonConvert.DeserializeObject<RootObject>(responseText);
                            tcs.SetResult(myResponse);
                        }
                    }, null);

            return tcs.Task;
        }

        public int GetTotalDriveTime()
        {
            int totalTime = 0;
            foreach (var results in _routeWazeResponse.response.results)
            {
                totalTime += results.crossTime;
            }
            return totalTime;
        }

        public List<Result> GetNearbyItems(Geocoordinate coord)
        {
            var nearbyItems = _routeWazeResponse.response.results.Where(
           item => Math.Abs(coord.Latitude - item.path.y) < 0.001
                   && Math.Abs(coord.Longitude - item.path.x) < 0.001
                   && item.wasRead == false)
                                           .ToList();

            //if (nearbyItems.Any())
            //{
            //    var result = nearbyItems.First();
            //    result.wasRead = true;
            //}

            return nearbyItems;
        }

        public void SetWasReadOnInstruction(Result result, bool wasRead)
        {
            var itemInList = _routeWazeResponse.response.results.Where(
           item => Math.Abs(result.path.y - item.path.y) < 0.001
                   && Math.Abs(result.path.x - item.path.x) < 0.001
                   && item.wasRead == false)
                                           .ToList();
            if (itemInList.Any())
            {
                itemInList.First().wasRead = true;
            }
        }

        public Result GetFirstPoint()
        {
            return RouteWazeResponse.response.results.FirstOrDefault();
        }

        public Result GetPointInInstruction(GeoCoordinate geoCoordinate)
        {
            return (from result in _routeWazeResponse.response.results
                    where
                        Math.Abs(result.path.x - geoCoordinate.Longitude) < 0.001 &&
                        Math.Abs(result.path.y - geoCoordinate.Latitude) < 0.001
                    select result).FirstOrDefault();
        }

        public bool DetrmainIfLastCoordinate(Geocoordinate coordinate)
        {
            var pointInRoute = (from coord in _routeWazeResponse.coords
                                where Math.Abs(coordinate.Latitude - coord.y) < 0.001 && Math.Abs(coordinate.Longitude - coord.x) < 0.001
                                select coord).FirstOrDefault();
            if (pointInRoute != null &&
                (Math.Abs(pointInRoute.x - _routeWazeResponse.coords.Last().x) < 0.001
                 && Math.Abs(pointInRoute.y - _routeWazeResponse.coords.Last().y) < 0.001))
            {
                return true;
            }
            return false;
        }
    }

    
}